import { PrismaService } from '@app/prisma';
import { UseGuards } from '@nestjs/common';
import { Args, Int, Mutation, Query, Resolver } from '@nestjs/graphql';
import { GqlAuthPowerGuard, AccountPower, GqlCurrentUser, GqlAuthGuard } from 'src/auth/auth.guard';
import { TaskEntity } from '@app/prisma/task.entity/task.entity';
import { AddTaskItemDto } from './dto/add-task.dto';
import { ClassesEntity } from '@app/prisma/classes.entity/classes.entity';
import { GetTaskTeachersDto } from './dto/get.task.teachers.dto';
import { Prisma } from '@prisma/client';
import { UserOnTaskPagination } from '@app/prisma/pagination/user.on.task.pagination';
import { TeacherEntity } from '@app/prisma/teacher.entity/teacher.entity';
import { TaskItemEntity } from '@app/prisma/task.item.entity/task.item.entity';
import { TaskOnTeacherItemEntity } from '@app/prisma/task.on.teacher.item.entity/task.on.teacher.item.entity';
import { UserEntity } from '@app/prisma/user.entity/user.entity';
import { AuthGuard } from '@nestjs/passport';
import { AddTaskRatesDto } from './dto/add.task.rates.dto';
import { ForbiddenError } from '@nestjs/apollo';



@Resolver()
export class TaskResolver {
  constructor(
    private readonly prisma: PrismaService
  ) { }

  /**
   * 获取与自己班级相关教师数量。
   * @param user 当前用户实体
   * @returns 返回与用户班级相关的教师数量
   */
  @Query(() => Int)
  @UseGuards(GqlAuthGuard)
  async getSelfTeacherCount(
    @GqlCurrentUser() user: UserEntity
  ) {
    const classes = await this.prisma.classes.findUnique({
      where: {
        id: user.classesId
      },
      include: {
        _count: {
          select: {
            TeacherOnClasses: true
          }
        }
      }
    })
    return classes._count.TeacherOnClasses
  }

  /**
   * 获取与自己相关的任务
   * @param user 当前用户实体
   * @returns 返回与用户相关的任务列表
   */
  @Query(() => [TaskEntity])
  @UseGuards(GqlAuthGuard)
  async getSelfTask(
    @GqlCurrentUser() user: UserEntity
  ) {
    if (!user.classesId) return []
    const res = await this.prisma.task.findMany({
      where: {
        TaskOnClasses: {
          some: {
            classesId: user.classesId,
          },
        },
        status: true
      },
      include: {
        _count: {
          select: {
            UserOnTask: {
              where: {
                userId: user.id
              }
            }
          }
        }
      },
      orderBy: {
        id: "desc"
      }
    })
    return res;
  }

  /**
   * 获取任务项目信息
   * @param id 任务ID
   * @returns 返回指定ID的任务信息，包括任务项目
   */
  @Query(() => TaskEntity)
  @UseGuards(GqlAuthGuard)
  getTaskItemInfo(
    @Args("id", { type: () => Int }) id: number
  ) {
    return this.prisma.task.findUniqueOrThrow({
      where: {
        id,
        status: true
      },
      include: {
        TaskItem: true
      }
    })
  }

  /**
   * 获取任务项目的教师信息
   * @param teacherId 教师ID
   * @returns 返回指定ID的教师信息
   */
  @Query(() => TeacherEntity)
  @UseGuards(GqlAuthGuard)
  getTaskItemTeacher(
    @Args("teacherId", { type: () => Int }) teacherId: number
  ) {
    return this.prisma.teacher.findUniqueOrThrow({
      where: {
        id: teacherId
      }
    })
  }

  /**
   * 获取一个任务所有的细节
   * @param id 任务ID
   * @param user 
   * @returns 
   */
  @Query(() => TaskEntity)
  @UseGuards(GqlAuthGuard)
  getSelfTaskDetail(
    @Args("id", { type: () => Int }) id: number,
    @GqlCurrentUser() user: UserEntity
  ) {
    if (!user.classesId || !id) return null;
    return this.prisma.task.findUniqueOrThrow({
      where: {
        id
      },
      include: {
        TaskItem: true,
        TaskOnClasses: {
          where: {
            classes: {
              User: {
                some: {
                  id: user.id
                }
              }
            }
          },
          include: {
            classes: {
              include: {
                TeacherOnClasses: {
                  include: {
                    teacher: true
                  }
                }
              }
            }
          }
        },
        UserOnTask: {
          where: {
            userId: user.id
          },
          include: {
            teacher: true,
            items: true
          }
        }
      }
    })
  }

  @Mutation(() => Int)
  @UseGuards(GqlAuthGuard)
  async commentTaskItem(
    @Args("id", { type: () => Int }) id: number,
    @Args("teacherId", { type: () => Int }) teacher_id: number,
    @Args("common", { nullable: true }) common: string,
    @Args("rates", { type: () => [AddTaskRatesDto] }) rates: AddTaskRatesDto[],
    @GqlCurrentUser() user: UserEntity
  ) {
    const task = await this.prisma.task.findUniqueOrThrow({
      where: {
        id
      },
      include: {
        TaskItem: true
      }
    })
    console.log(1)
    if (rates.length !== task.TaskItem.length) {
      throw new ForbiddenError("提交数据样本异常，请重试")
    }
    console.log(2)
    await this.prisma.userOnTask.create({
      data: {
        user: {
          connect: {
            id: user.id
          }
        },
        teacher: {
          connect: {
            id: teacher_id
          }
        },
        common,
        task: {
          connect: {
            id
          }
        }
      }
    })
    console.log(3)
    await this.prisma.userTaskItem.createMany({
      data: task.TaskItem.map(({ id }) => {
        return {
          taskItemId: id,
          userOnTaskUserId: user.id,
          userOnTaskTaskId: task.id,
          userOnTaskTeacherId: teacher_id,
          score: rates.find(e => e.id === id).rate
        }
      })
    })
    for (const item of task.TaskItem) {
      console.log(rates, item)
      await this.prisma.taskOnTeacherItem.update({
        where: {
          taskItemId_teacherId: {
            teacherId: teacher_id,
            taskItemId: item.id
          }
        },
        data: {
          score: {
            increment: rates.find(e => e.id === item.id).rate,
          },
          count: {
            increment: 1
          }
        }
      })
    }
    console.log(5)
    return id
  }

  // @Mutation(() =>)
  // @UseGuards(GqlAuthGuard)
  // sendTask(
  //   @Args("form") form: any[],
  //   @Args("id") id: number,
  //   @Args("common") common: string,
  //   @Args("teacherId", { type: () => Int }) teacherId: number
  // ) {

  // }





  /**
   * 获取教师分析数据
   * @returns 返回所有教师的分析数据，包括每个任务项目的平均分数
   */
  @Query(() => [TeacherEntity])
  async getTeacherAnalysis() {
    const teachers = await this.prisma.teacher.findMany({ orderBy: { id: "desc" } });

    const items = await this.prisma.taskItem.findMany({
      select: {
        name: true,
        id: true
      }
    })
    const res = await this.prisma.userTaskItem.groupBy({
      by: ["userOnTaskTeacherId", "taskItemId"],
      _avg: {
        score: true
      }
    })
    return teachers.map((teacher) => {
      const data = items.reduce((acc, item) => {
        if (!acc[item.name]) acc[item.name] = {
          length: 0,
          sum: 0
        };
        res.forEach(line => {
          if (line.taskItemId === item.id) {
            acc[item.name].length++;
            acc[item.name].sum += line._avg.score
          }
        })
        return acc;
      }, {} as { [key in string]: {
        length: number,
        sum: number
      } });
      return {
        ...teacher,
        items: Object.keys(data).map(name => {
          return ({
            name,
            avg: data[name].sum / (data[name].length || 1)
          })
        }).filter(e => !!e.avg)
      }
    })
  }

  /**
   * 获取任务评论
   * @param taskId 任务ID
   * @param teacherId 教师ID（可选）
   * @param classesId 班级ID（可选）
   * @param skip 跳过的记录数
   * @param take 获取的记录数
   * @returns 返回分页后的任务评论数据
   */
  @Query(() => UserOnTaskPagination)
  async getTaskComment(
    @Args("id", { type: () => Int }) taskId: number,
    @Args("teacherId", { type: () => Int, nullable: true }) teacherId?: number,
    @Args("classesId", { type: () => Int, nullable: true }) classesId?: number,
    @Args("skip", { type: () => Int, nullable: true }) skip = 0,
    @Args("take", { type: () => Int, nullable: true }) take = 20
  ) {
    const where: Prisma.UserOnTaskWhereInput = {
      taskId,
      common: {
        not: '',
      }
    };
    if (!!teacherId) {
      where.teacherId = teacherId
    }
    if (!!classesId) {
      where.user = {
        classesId
      }
    }
    const total = await this.prisma.userOnTask.count({ where });
    const data = await this.prisma.userOnTask.findMany({
      where,
      skip,
      take,
      orderBy: {
        incId: "desc"
      }
    })
    return {
      skip,
      take,
      total,
      count: data.length,
      data
    }
  }

  /**
   * 获取所有任务及其完成情况
   * @returns 返回所有任务的详细信息，包括完成数量和总数
   */
  @Query(() => [TaskEntity])
  async getAllTaskAndFinished() {
    const tasks = await this.prisma.task.findMany({
      orderBy: {
        id: "desc"
      }
    });
    const result = [];
    for (const task of tasks) {
      const userCount = await this.prisma.user.count({
        where: {
          classes: {
            TaskOnClasses: {
              some: {
                taskId: task.id
              }
            }
          }
        }
      });
      const finishedCount = await this.prisma.userOnTask.count({
        where: {
          taskId: task.id
        }
      })
      const teacherCount = await this.prisma.teacher.count({
        where: {
          TeacherOnClasses: {
            some: {
              classes: {
                TaskOnClasses: {
                  some: {
                    taskId: task.id
                  }
                }
              }
            }
          }
        }
      })
      const total = teacherCount * userCount;
      result.push({
        ...task,
        userCount,
        teacherCount,
        finishedCount,
        total
      })
    }
    return result;
  }

  /**
   * 获取所有任务
   * @returns 返回所有任务的信息，包括任务项目
   */
  @Query(() => [TaskEntity])
  getAllTask() {
    return this.prisma.task.findMany({
      orderBy: {
        id: "desc"
      },
      include: {
        TaskItem: true
      }
    })
  }

  /**
   * 获取特定教师的任务项目详情
   * @param id 任务ID
   * @param teacherId 教师ID
   * @returns 返回指定任务的详细信息，包括任务项目
   */
  @Mutation(() => TaskEntity)
  async getTaskItemDetailByTeacher(
    @Args("id", { type: () => Int }) id: number,
    @Args("teacherId", { type: () => Int }) teacherId: number
  ) {
    return await this.prisma.task.findUnique({
      where: {
        id
      },
      include: {
        TaskItem: true
      }
    })
  }

  /**
   * 获取任务项目
   * @param id 任务ID
   * @returns 返回指定任务的详细信息，包括任务项目
   */
  @Query(() => TaskEntity)
  getTaskItems(
    @Args("id", { type: () => Int }) id: number
  ) {
    return this.prisma.task.findUnique({
      where: {
        id
      },
      include: {
        TaskItem: true
      }
    })
  }

  /**
   * 根据教师ID获取任务项目
   * @param id 任务项目ID
   * @param userOnTaskTeacherId 用户任务教师ID
   * @returns 返回指定任务项目的详细信息，包括用户任务项目
   */
  @Query(() => TaskItemEntity)
  getTaskItemByTeacherId(
    @Args("id", { type: () => Int }) id: number,
    @Args("userOnTaskTeacherId", { type: () => Int }) userOnTaskTeacherId: number
  ) {
    return this.prisma.taskItem.findUnique({
      where: {
        id
      },
      include: {
        UserTaskItem: {
          where: {
            userOnTaskTeacherId
          }
        }
      }
    })
  }


  /**
   * 获取特定班级的任务项目详情
   * @param id 任务ID
   * @param classesId 班级ID
   * @returns 返回指定班级的任务详细信息，包括用户和用户任务
   */
  @Mutation(() => ClassesEntity)
  async getTaskItemDetailByClasses(
    @Args("id", { type: () => Int }) id: number,
    @Args("classesId", { type: () => Int }) classesId: number
  ) {
    return await this.prisma.classes.findUnique({
      where: {
        id: classesId,
        TaskOnClasses: {
          some: {
            taskId: id
          }
        }
      },
      include: {
        User: {
          include: {
            UserOnTask: {
              where: {
                taskId: id
              }
            },
            profile: true
          }
        }
      }
    })
  }

  /**
   * 获取特定任务和班级的完成数量
   * @param taskId 任务ID
   * @param classesId 班级ID
   * @returns 返回指定任务和班级的完成数量
   */
  @Query(() => Int)
  getTaskClassesFinished(
    @Args("taskId", { type: () => Int }) taskId: number,
    @Args("classesId", { type: () => Int }) classesId: number
  ) {
    return this.prisma.userOnTask.count({
      where: {
        taskId,
        user: {
          classesId
        }
      }
    })
  }

  /**
   * 获取任务班级详情
   * @param id 任务ID
   * @returns 返回指定任务的详细信息，包括任务班级和任务项目
   */
  @Query(() => TaskEntity)
  async getTaskClassesDetail(
    @Args("id", { type: () => Int }) id: number
  ) {
    return this.prisma.task.findUnique({
      where: {
        id
      },
      include: {
        TaskOnClasses: {
          include: {
            classes: {
              include: {
                _count: true
              },
            },
          }
        },
        TaskItem: true
      }
    });
  }



  /**
   * 获取任务教师详情
   * @param id 任务ID
   * @returns 返回指定任务的教师详细信息，包括总数和完成数
   */
  @Query(() => [GetTaskTeachersDto])
  async getTaskTeachersDetail(
    @Args("id", { type: () => Int }) id: number
  ) {
    const teachers = await this.prisma.teacher.findMany({
      where: {
        TeacherOnClasses: {
          some: {
            classes: {
              TaskOnClasses: {
                some: {
                  taskId: id
                }
              }
            }
          }
        }
      }
    })
    const res = [];
    for (const teacher of teachers) {
      //查询学生的班级是否参与了task,并且该班级存在该教师
      const total = await this.prisma.user.count({
        where: {
          classes: {
            TaskOnClasses: {
              some: {
                taskId: id,

              }
            },
            TeacherOnClasses: {
              some: {
                teacherId: teacher.id
              }
            }
          }
        }
      })
      //查询该任务、该教师下的userOnTask有多少个
      const finished = await this.prisma.userOnTask.count({
        where: {
          taskId: id,
          teacherId: teacher.id
        }
      })
      res.push({ total, finished, teacher })
    }
    return res
  }

  /**
   * 根据ID获取任务
   * @param id 任务ID
   * @returns 返回指定ID的任务信息，包括任务项目
   */
  @Mutation(() => TaskEntity)
  getTaskById(
    @Args("id", { type: () => Int }) id: number
  ) {
    return this.prisma.task.findUniqueOrThrow({
      where: {
        id
      },
      include: {
        TaskItem: true
      }
    })
  }


  /**
   * 添加或更新任务
   * @param title 任务标题
   * @param select 选择的班级
   * @param items 任务项目
   * @param startTime 开始时间
   * @param deadline 截止时间
   * @param status 任务状态
   * @param id 任务ID（可选，用于更新）
   * @param comment 任务评论（可选）
   * @returns 返回创建或更新后的任务信息
   */
  @Mutation(() => TaskEntity)
  @UseGuards(new GqlAuthPowerGuard(AccountPower))
  async addTask(
    @Args("title") title: string,
    @Args("select") select: string,
    @Args("items", { type: () => [AddTaskItemDto] }) items: AddTaskItemDto[],
    @Args("status", { type: () => Boolean }) status: boolean,
    @Args("id", { type: () => Int, nullable: true }) id?: number,
    @Args("comment", { nullable: true }) comment?: string
  ) {
    let task: TaskEntity;
    if (!!id) {
      await this.prisma.userTaskItem.deleteMany({
        where: {
          userOnTaskTaskId: id
        }
      })
      await this.prisma.taskOnTeacherItem.deleteMany({
        where: {
          taskItem: {
            taskId: id
          }
        }
      })
      task = await this.prisma.task.update({
        where: {
          id
        },
        data: {
          title,
          select,
          status,
          comment,
          TaskItem: {
            deleteMany: {},
            create: items.map((item) => ({
              name: item.name,
              comment: item.comment
            })),
          },
          UserOnTask: {
            deleteMany: {}
          },
          TaskOnClasses: {
            deleteMany: {},
            create: JSON.parse(select).filter(e => {
              const s = e.split("_");
              if (s.length !== 4) return false;
              return true;
            }).map((e) => {
              const s = e.split("_");
              const classesId = parseInt(s.pop())
              return {
                classesId
              }
            })
          }
        },
        include: {
          TaskItem: true,
          TaskOnClasses: {
            include: {
              classes: {
                include: {
                  TeacherOnClasses: true
                }
              }
            }
          }
        }
      })
    } else {
      task = await this.prisma.task.create({
        data: {
          title,
          select,
          comment,
          status,
          TaskItem: {
            create: items.map((item) => ({
              name: item.name,
              comment: item.comment,
            })),
          },
          TaskOnClasses: {
            create: JSON.parse(select).filter(e => {
              const s = e.split("_");
              if (s.length !== 4) return false;
              return true;
            }).map((e) => {
              const s = e.split("_");
              const classesId = parseInt(s.pop())
              return {
                classesId
              }
            })
          }
        },
        include: {
          TaskItem: true,
          TaskOnClasses: {
            include: {
              classes: {
                include: {
                  TeacherOnClasses: true
                }
              }
            }
          }
        }
      });
    }
    const teacherIds = [...new Set(task.TaskOnClasses.map(e => e.classes).flat().map(e => e.TeacherOnClasses).flat().map(e => e.teacherId))];
    for (const item of task.TaskItem) {
      await this.prisma.taskOnTeacherItem.createMany({
        data: teacherIds.map((teacherId) => ({
          taskItemId: item.id,
          teacherId
        }))
      })
    }
    return task;
  }

  /**
   * 获取教师的任务项目
   * @param taskId 任务ID
   * @param teacherId 教师ID
   * @returns 返回指定任务和教师的任务项目信息
   */
  @Query(() => [TaskOnTeacherItemEntity])
  async getTeacherOnTaskItems(
    @Args("taskId", { type: () => Int }) taskId: number,
    @Args("teacherId", { type: () => Int }) teacherId: number
  ) {
    const task = await this.prisma.task.findUnique({
      where: {
        id: taskId

      },
      include: {
        TaskItem: true
      }
    })
    const result = [];
    for (const item of task.TaskItem) {
      const taskOnTeacherItem = await this.prisma.taskOnTeacherItem.findUnique({
        where: {
          taskItemId_teacherId: {
            teacherId,
            taskItemId: item.id
          }
        }
      })
      result.push({
        ...taskOnTeacherItem,
        taskItem: item
      });
    }
    return result;
  }

  /**
   * 删除任务
   * @param id 任务ID
   * @returns 返回被删除的任务信息
   */
  @Mutation(() => TaskEntity)
  @UseGuards(new GqlAuthPowerGuard(AccountPower))
  async delTask(
    @Args('id', { type: () => Int }) id: number
  ) {
    const task = await this.prisma.task.findUnique({
      where: {
        id
      },
      include: {
        TaskItem: true
      }
    });
    for (const item of task.TaskItem) {
      await this.prisma.taskOnTeacherItem.deleteMany({
        where: {
          taskItemId: item.id
        }
      })
    }
    await this.prisma.userTaskItem.deleteMany({
      where: {
        userOnTaskTaskId: id
      }
    })
    await this.prisma.userOnTask.deleteMany({
      where: {
        taskId: id
      }
    })
    await this.prisma.taskItem.deleteMany({
      where: {
        taskId: id
      }
    })

    await this.prisma.taskOnClasses.deleteMany({
      where: {
        taskId: id
      }
    })
    return await this.prisma.task.delete({
      where: {
        id
      }
    })
  }

}
